﻿<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>39_2D3D</title>
    <link href="css/common.css" rel="stylesheet" />
    <script src="js/gl-matrix.js"></script>
</head>
<body>
    <canvas id="mycanvas"></canvas>
    <script id="shader-vs" type="x-shader/x-vertex">
        attribute vec4 aPosition;
        attribute vec4 aColor;
        attribute vec2 aTexCoord;

        uniform mat4 uModelMatrix;
        uniform mat4 uViewMatrix;
        uniform mat4 uProjMatrix;

        varying vec4 vColor;
        varying vec2 vTexCoord;

        void main() {
        gl_Position = uProjMatrix *  uViewMatrix * uModelMatrix * aPosition;
        vColor = aColor;
        vTexCoord = aTexCoord;
        }
    </script>
    <script id="shader-fs" type="x-shader/x-fragment">
        precision mediump float;

        uniform int uUseTexture;
        uniform sampler2D uSampler;

        varying vec4 vColor;
        varying vec2 vTexCoord;

        void main() {
        if(uUseTexture == 1) {
        gl_FragColor = texture2D(uSampler, vTexCoord);
        } else {
        gl_FragColor = vColor;
        }
        }
    </script>
    <script>
        var canvas = document.getElementById('mycanvas');
        canvas.width = canvas.clientWidth;
        canvas.height = canvas.clientHeight;

        var gl = canvas.getContext('webgl');

        var vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader, document.getElementById('shader-vs').innerHTML);
        gl.compileShader(vertexShader);

        var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragmentShader, document.getElementById('shader-fs').innerHTML);
        gl.compileShader(fragmentShader);

        var shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertexShader);
        gl.attachShader(shaderProgram, fragmentShader);
        gl.linkProgram(shaderProgram);
        gl.useProgram(shaderProgram);

        var aPosition = gl.getAttribLocation(shaderProgram, 'aPosition');
        var aColor = gl.getAttribLocation(shaderProgram, 'aColor');
        var aTexCoord = gl.getAttribLocation(shaderProgram, 'aTexCoord');
        var uModelMatrix = gl.getUniformLocation(shaderProgram, 'uModelMatrix');
        var uViewMatrix = gl.getUniformLocation(shaderProgram, 'uViewMatrix');
        var uProjMatrix = gl.getUniformLocation(shaderProgram, 'uProjMatrix');
        var uUseTexture = gl.getUniformLocation(shaderProgram, 'uUseTexture');
        var uSampler = gl.getUniformLocation(shaderProgram, 'uSampler');

        /**************************** 正方体 *********************************/

        // 模型矩阵
        var model = mat4.rotateX(mat4.create(), mat4.create(), 0);
        gl.uniformMatrix4fv(uModelMatrix, false, model);

        // 视图矩阵
        var view = mat4.lookAt(mat4.create(), vec3.fromValues(1, 1.5, 2), vec3.fromValues(0, 0, 0), vec3.fromValues(1, 0, 0));
        gl.uniformMatrix4fv(uViewMatrix, false, view);

        // 视图矩阵2d
        var view2d = mat4.lookAt(mat4.create(), vec3.fromValues(0, 0, 10), vec3.fromValues(0, 0, 0), vec3.fromValues(0, 1, 0));

        // 投影矩阵
        var proj = mat4.perspective(mat4.create(), Math.PI * 90 / 180, canvas.width / canvas.height, 0.1, 10000);
        gl.uniformMatrix4fv(uProjMatrix, false, proj);

        // 投影矩阵2d
        var proj2d = mat4.create();
        mat4.ortho(proj2d, -1, 1, -1, 1, 0, 10000);

        // 顶点位置矩阵
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
             1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0,  // v0-v1-v2-v3 front
             1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0,  // v0-v3-v4-v5 right
             1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0,  // v0-v5-v6-v1 up
            -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0,  // v1-v6-v7-v2 left
            -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,  // v7-v4-v3-v2 down
             1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0   // v4-v7-v6-v5 back
        ]), gl.STATIC_DRAW);

        gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aPosition);

        // 顶点颜色矩阵
        var colorBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
            0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0,  // v0-v1-v2-v3 front(blue)
            0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4,  // v0-v3-v4-v5 right(green)
            1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4,  // v0-v5-v6-v1 up(red)
            1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4,  // v1-v6-v7-v2 left
            1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,  // v7-v4-v3-v2 down
            0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0   // v4-v7-v6-v5 back
        ]), gl.STATIC_DRAW);

        gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aColor);

        // uv坐标矩阵
        var uvBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
          1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,    // v0-v1-v2-v3 front
          0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0,    // v0-v3-v4-v5 right
          1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,    // v0-v5-v6-v1 up
          1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,    // v1-v6-v7-v2 left
          0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,    // v7-v4-v3-v2 down
          0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0     // v4-v7-v6-v5 back
        ]), gl.STATIC_DRAW);

        gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aTexCoord);

        // 索引矩阵
        var indexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([
             0, 1, 2, 0, 2, 3,    // front
             4, 5, 6, 4, 6, 7,    // right
             8, 9, 10, 8, 10, 11,    // up
            12, 13, 14, 12, 14, 15,    // left
            16, 17, 18, 16, 18, 19,    // down
            20, 21, 22, 20, 22, 23     // back
        ]), gl.STATIC_DRAW);

        /********************************* 绘制2d平板 *********************************/

        // 顶点位置矩阵
        var positionBuffer2 = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer2);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
             -1.0, -1.0, 0.0,
             1.0, -1.0, 0.0,
             1.0, 1.0, 0.0,
             -1.0, 1.0, 0.0
        ]), gl.STATIC_DRAW);

        gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aPosition);

        // 顶点颜色矩阵
        var colorBuffer2 = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer2);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
            0.4, 0.4, 0.4,
            0.4, 0.4, 0.4,
            0.4, 0.4, 0.4,
            0.4, 0.4, 0.4,
        ]), gl.STATIC_DRAW);

        gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aColor);

        // uv坐标矩阵
        var uvBuffer2 = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer2);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
            0.0, 0.0,
            1.0, 0.0,
            1.0, 1.0,
            0.0, 1.0
        ]), gl.STATIC_DRAW);
        gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aTexCoord);

        // 索引矩阵
        var indexBuffer2 = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer2);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([
             0, 1, 2,
             0, 2, 3,
        ]), gl.STATIC_DRAW);

        // 纹理
        var canvas2d = document.createElement('canvas');
        canvas2d.width = canvas.width;
        canvas2d.height = canvas.height;
        var ctx = canvas2d.getContext('2d');
        ctx.fillStyle = 'rgba(0,0,0,0.5)';
        ctx.fillRect(0, 0, canvas2d.width, canvas2d.height);
        ctx.fillStyle = '#ff0000';
        ctx.fillRect(30, 30, 300, 200);
        ctx.font = "40px 微软雅黑";
        ctx.fillText('平板是半透明的，这是写在平板上的一些字。', 30, 300);

        var texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.activeTexture(gl.TEXTURE0);
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.uniform1i(uSampler, 0);

        // 渲染
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

        var xAxisAngle = 0;
        var yAxisAngle = 0;

        var render = function () {
            xAxisAngle += Math.PI / 180;
            yAxisAngle += Math.PI / 180;
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

            // 绘制正方体
            mat4.rotateX(model, mat4.create(), xAxisAngle);
            mat4.rotateY(model, model, xAxisAngle);
            gl.uniformMatrix4fv(uModelMatrix, false, model);
            gl.uniformMatrix4fv(uViewMatrix, false, view);
            gl.uniformMatrix4fv(uProjMatrix, false, proj);
            gl.uniform1i(uUseTexture, 0);
            gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
            gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 0, 0);

            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
            gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);
            gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
            gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 0, 0);
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
            gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0);

            // 在平板上写字
            ctx.fillStyle = 'rgba(1,0,0,0.2)';
            //ctx.fillRect(0, 0, canvas2d.width, canvas2d.height);
            //gl.bindTexture(gl.TEXTURE_2D, texture);
            //gl.activeTexture(gl.TEXTURE0);
            //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
            gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
            //gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            //gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
            //gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
            //gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            //gl.uniform1i(uSampler, 0);

            // 绘制2d物体
            mat4.rotateX(model, mat4.create(), 0);
            gl.uniformMatrix4fv(uModelMatrix, false, model);
            gl.uniformMatrix4fv(uViewMatrix, false, view2d);
            gl.uniformMatrix4fv(uProjMatrix, false, proj2d);
            gl.uniform1i(uUseTexture, 1);
            gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer2);
            gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 0, 0);
            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer2);
            gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);
            gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer2);
            gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 0, 0);
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer2);
            gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
        }

        var tick = function () {
            requestAnimationFrame(tick);
            render();
        }
        tick();
    </script>
</body>
</html>
